
package com.hexinfo.dmpro.sparing.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hexinfo.dmpro.common.model.ClusterSparingConf;
import com.hexinfo.dmpro.common.model.MessageCenter;
import com.hexinfo.dmpro.common.service.MessageCenterService;
import com.hexinfo.dmpro.common.utils.CommonConstants;
import com.hexinfo.dmpro.common.utils.FileUtil;
import com.hexinfo.dmpro.common.utils.ScanCommonConstants;
import com.hexinfo.dmpro.sparing.dto.HdfsDistcpDTO;
import com.hexinfo.dmpro.sparing.dto.TableDistCPDTO;
import com.hexinfo.dmpro.sparing.dto.TbHdfsDistcpDTO;
import com.hexinfo.dmpro.sparing.model.HdfsHeatBackup;
import com.hexinfo.dmpro.sparing.model.ScanMetadataWguat;
import com.hexinfo.dmpro.sparing.dao.ScanMetadataWguatMapper;
import com.hexinfo.dmpro.sparing.service.RuleToDistCPService;
import com.hexinfo.dmpro.sparing.service.ScanMetadataService;
import com.hexinfo.dmpro.sparing.service.ScanMetadataWguatService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * 万国UAT元数据扫描表
 *
 * @author yemw
 * @date 2023-10-09 11:15:32
 */
@Service
@AllArgsConstructor
@Slf4j
public class ScanMetadataWguatServiceImpl extends ServiceImpl<ScanMetadataWguatMapper, ScanMetadataWguat> implements ScanMetadataWguatService {

    private final ScanMetadataService scanMetadataService;

    private final RuleToDistCPService ruleToDistCPService;

    private final MessageCenterService messageCenterService;

    @Override
    public Page queryList(Page page, ScanMetadataWguat scanMetadataWguat) {
        LambdaQueryWrapper<ScanMetadataWguat> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StrUtil.isNotBlank(scanMetadataWguat.getTblDatabaseName()),ScanMetadataWguat::getTblDatabaseName,scanMetadataWguat.getTblDatabaseName())
                .like(StrUtil.isNotBlank(scanMetadataWguat.getTblName()),ScanMetadataWguat::getTblName,scanMetadataWguat.getTblName())
                .eq(ScanMetadataWguat::getDel,CommonConstants.STATUS_NORMAL);
        Page returnPage = this.baseMapper.selectPage(page, wrapper);
        return returnPage;
    }

    @Override
    public List<List<Object>> readExcel(MultipartFile file) throws Exception{
//        File toFile = new File("D:\\项目相关文件\\兴全\\测试.xlsx");
        File toFile = this.multipartFileToFile(file);
        List<List<Object>> lists = new ArrayList<>();
        if (!toFile.exists()) {
            throw new Exception("文件不存在!");
        }
        try (FileInputStream fileInputStream = new FileInputStream(toFile)) {
            lists = FileUtil.readExcel(fileInputStream);

        }
        return lists;
    }
    @Override
    public Map<String,String> testSync(MultipartFile file) throws Exception {
        //消息中心
        MessageCenter mess = new MessageCenter();
        mess.setMenu(ScanCommonConstants.ClusterName.SJRB.value);
        mess.setOperator("admin");
        mess.setDataType(ScanCommonConstants.ClusterName.JXZ.value);
        mess.setMessageSubject(ScanCommonConstants.ClusterName.CSSJTB.value);
        mess.setMessageWeight(ScanCommonConstants.ClusterName.ONE.value);
        messageCenterService.save(mess);
        Map<String,String> map  = new HashMap<>();
        List<TbHdfsDistcpDTO> distcpDTOList = new ArrayList<>();
        List<ScanMetadataWguat> scanMetadataWguats = new ArrayList<>();
        Map<String,List<HdfsDistcpDTO>> listMap = new HashMap<>();
        List<List<Object>> lists = this.readExcel(file);
        if(!"库名".equals(lists.get(0).get(0))){
            map.put("error","excel模板异常，请检查模板");
            return map;
        }
        //查询集群信息
        LambdaQueryWrapper<ClusterSparingConf> uATWrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<ClusterSparingConf> wGWrapper = Wrappers.lambdaQuery();
        ClusterSparingConf uATCluster = scanMetadataService.wrapperClusterSparingConf(uATWrapper,"UAT");
        ClusterSparingConf wGCluster = scanMetadataService.wrapperClusterSparingConf(wGWrapper,"万国");
        for (List<Object> objectList: lists) {
            ScanMetadataWguat wguat = new ScanMetadataWguat();
            if("库名".equals(objectList.get(0))){
                continue;
            }
            //库名
            wguat.setTblDatabaseName(objectList.get(0).toString());
            //表名
            wguat.setTblName(objectList.get(1).toString());
            //分区信息
            wguat.setPartName(objectList.get(2).toString());
            //hdfs路径拼接
            if(StrUtil.isNotBlank(wguat.getPartName())){
                wguat.setLocation(wGCluster.getHdfsPrefixPath()+wguat.getTblDatabaseName()+".db/"+wguat.getTblName()+"/"+wguat.getPartName());
            }else{
                wguat.setLocation(wGCluster.getHdfsPrefixPath()+wguat.getTblDatabaseName()+".db/"+wguat.getTblName());
            }
            listMap.put(wguat.getTblDatabaseName()+"."+wguat.getTblName(),new ArrayList<HdfsDistcpDTO>());
            scanMetadataWguats.add(wguat);
        }
        //存储到数据库
        this.saveBatch(scanMetadataWguats);
        //数据结构转换
        for (ScanMetadataWguat wguat: scanMetadataWguats) {
            HdfsDistcpDTO hdfs = new HdfsDistcpDTO();
            hdfs.setSourceAddress(wguat.getLocation());
            hdfs.setTargetAddress(StrUtil.replace(StrUtil.replace(wguat.getLocation(),uATCluster.getHdfsPrefixPath(),wGCluster.getHdfsPrefixPath()),"/"+wguat.getTblDatabaseName()+".db/","/uat_"+wguat.getTblDatabaseName()+".db/"));
            listMap.get(wguat.getTblDatabaseName()+"."+wguat.getTblName()).add(hdfs);

        }
        for (String key: listMap.keySet()) {
            TbHdfsDistcpDTO dto = new TbHdfsDistcpDTO();
            dto.setDbTbNameSou(key);
            dto.setDbTbNameTar("uat_"+key);
            dto.setHdfsDistcpDTOS(listMap.get(key));
            distcpDTOList.add(dto);
        }
        ruleToDistCPService.hdfsDistcp(distcpDTOList, DateUtil.format(new Date(), "yyyyMMddHHmmss"),mess.getId());
        map.put("success","当前导入"+ (lists.size()-1) +"条数据");
        return map;
    }

    @Override
    public void getFiles(String flag, HttpServletResponse response) {
        OutputStream os;//新建一个输出流对象
//        String basePath = "D:\\code\\xq\\dmpro\\dmpro-sparing\\src\\main\\resources\\files\\"; //定义文件上传的根路径
        String basePath = "/opt/dmpro/file/";
        List<String> fileNames = FileUtil.listFileNames(basePath);//获取所有的文件名称
        log.info("===========================UAT测试环境导入模板下载");
        String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");//找到跟参数一致的文件
        try {
            if(StrUtil.isNotEmpty(fileName)){
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                response.setContentType("application/octet-stream");
                byte[] bytes = FileUtil.readBytes(basePath + fileName);//通过文件的路径读取文件字节流
                os = response.getOutputStream();//通过response的输出流返回文件
                os.write(bytes);
                os.flush();
                os.close();
            }
        }catch (Exception e){
            System.out.println("文件下载失败");
        }
    }

    /**
     * @Description 将MultipartFile转换为File
     * @param multiFile
     * @return
     */
    private  File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若须要防止生成的临时文件重复,能够在文件名后添加随机码
        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
